/*
Copyright (C) 2022-2024 Inspur Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package service

import (
	"icep/bean/entity"
	"icep/chain/artifact"
	"icep/chain/client"
	"icep/common/logger"
	"icep/config"

	"github.com/go-xorm/xorm"
)

var log = logger.GetLogger("service")

const (
	AlgGM         = "GM"
	AlgSW         = "SW"
	HashAlgSm3    = "GMSM3"
	HashAlgSha256 = "SHA2"
)

type IcepService struct {
	DbEngine *xorm.Engine
}

func NewIcepService(engine *xorm.Engine) *IcepService {
	return &IcepService{
		DbEngine: engine,
	}
}

func (is *IcepService) GetChainClient(tenantId string) *client.IchainClient {
	tenants := make([]*entity.IcepTenant, 0)
	err := is.DbEngine.Where("id = ?", tenantId).Find(&tenants)
	if err != nil {
		log.Errorf("get ichain client, query tenant error: %v", err)
		return nil
	}
	if len(tenants) <= 0 {
		log.Errorf("get ichain client, can not find tenant, tennant id = %s", tenantId)
		return nil
	}

	identities := make([]*entity.IcepTenantIdentity, 0)
	err = is.DbEngine.Where("tenant_id = ? and status = '1'", tenantId).Find(&identities)
	if err != nil {
		log.Errorf("get ichain client, query identity error: %v", err)
		return nil
	}
	if len(identities) <= 0 {
		log.Errorf("get ichain client, can not find identity, tenant id = %s", tenantId)
		return nil
	}

	consenserEntities := make([]*entity.IcepChainConsenser, 0)
	err = is.DbEngine.Where("tenant_id = ?", tenantId).Find(&consenserEntities)
	if err != nil {
		log.Errorf("get ichain client, query consenser error: %v", err)
		return nil
	}
	if len(consenserEntities) <= 0 {
		log.Errorf("get ichain client, can not find consenser, tenant id = %s", tenantId)
		return nil
	}

	consensers := make([]artifact.Node, 0)
	for _, ce := range consenserEntities {
		consenser := artifact.Node{
			NodeName: ce.Name,
			Host:     ce.Host,
			Port:     ce.Port,
		}
		consensers = append(consensers, consenser)
	}

	orgEntities := make([]*entity.IcepChainOrg, 0)
	err = is.DbEngine.Where("tenant_id = ?", tenantId).Find(&orgEntities)
	if err != nil {
		log.Errorf("get ichain client, query org error: %v", err)
		return nil
	}
	if len(orgEntities) <= 0 {
		log.Errorf("get ichain client, can not find org, tenant id = %s", tenantId)
		return nil
	}

	orgs := make([]artifact.Org, 0)
	nodes := make([]string, 0)
	config.Get("icep.chain.org-crypto-path", "")
	for _, orgEntity := range orgEntities {
		nodeEntities := make([]*entity.IcepChainNode, 0)
		err := is.DbEngine.Where("org_id = ?", orgEntity.Id).Find(&nodeEntities)
		if err != nil {
			log.Errorf("get ichain client, query node error: %v", err)
			return nil
		}
		if len(nodeEntities) <= 0 {
			log.Errorf("get ichain client, can not find node, org id = %s", orgEntity.Id)
			return nil
		}

		org := artifact.Org{
			OrgName:    orgEntity.OrgName,
			IamId:      orgEntity.IamId,
			CryptoPath: config.Get("icep.chain.org-crypto-path", orgEntity.CryptoPath),
			Nodes:      []artifact.Node{},
		}
		for _, nodeEntity := range nodeEntities {
			node := artifact.Node{
				NodeName: nodeEntity.Name,
				Host:     nodeEntity.Host,
				Port:     nodeEntity.Port,
			}
			org.Nodes = append(org.Nodes, node)
			nodes = append(nodes, node.NodeName)
		}
		orgs = append(orgs, org)
	}

	alg := config.Get("icep.chain.alg", AlgGM)
	hash := HashAlgSm3

	if alg == AlgSW {
		hash = HashAlgSha256
	} else {
		alg = AlgGM
		hash = HashAlgSm3
	}
	cc := client.NewClient(client.Config{
		TenantId:    tenantId,
		OrgName:     tenants[0].OrgName,
		ServiceName: tenants[0].LeagueName,
		ChainName:   tenants[0].ChainName,
		Orgs:        orgs,
		Consensers:  consensers,
		Nodes:       nodes,
		Cert:        []byte(identities[0].Cert),
		PrvKey:      []byte(identities[0].PrvKey),
		ChainLog:    config.Get("icep.chain.log", "debug"),
		Alg:         alg,
		HashAlg:     hash,
	})
	err = cc.Initialize()
	if err != nil {
		return nil
	}
	return cc
}
